package com.ys.service.finance.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.finance.TcwAccountDetailedForCompany;
import com.ys.entity.finance.TcwExpenseSettleReturn;
import com.ys.entity.finance.TcwExpenseSettleReturnItem;
import com.ys.entity.flow.YspModel;
import com.ys.entity.sys.*;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.finance.*;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.finance.TcwExpenseSettleReturnService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;

/**
 * 费用结算返还单
 */
@Service("tcwExpenseSettleReturnService")
public class TcwExpenseSettleReturnServiceImpl implements TcwExpenseSettleReturnService {
	private static final Logger logger = LoggerFactory.getLogger(TcwExpenseSettleReturnServiceImpl.class);

	@Autowired
	private TcwExpenseSettleReturnMapper tcwExpenseSettleReturnMapper;

	@Autowired
	private TcwExpenseSettleReturnItemMapper tcwExpenseSettleReturnItemMapper;

	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private FinanceMapper financeMapper;

	@Autowired
	private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;

	/**
	 * 新增
	 */
	@Override
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwExpenseSettleReturn entity = JSON.parseObject(JSON.toJSONString(params), TcwExpenseSettleReturn.class);
		entity.setStatus(1);//状态
		entity.setEffectStock(0);//审批状态

		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setOrderby("A.CreateTime DESC").queryFirst();
		if(tsUserChange!=null){
			entity.setCreateChangeId(tsUserChange.getId());//制单人变更信息
		}else {
			return R.error("未查询到制单人信息！");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}

		//新增
		tcwExpenseSettleReturnMapper.insert(entity);

		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, entity.getBid(), createUserId);
		}
		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/finance/tcwExpenseSettleReturn/toEdit?bid=" + entity.getBid()));
	}


	/**
	 * 修改
	 */
	@Override
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwExpenseSettleReturn entity = JSON.parseObject(JSON.toJSONString(params), TcwExpenseSettleReturn.class);
		// 验证状态
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst == null) {
			return R.error("审批数据不存在，无法编辑");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value) {
			return R.error("已流转，无法编辑");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}
		tcwExpenseSettleReturnMapper.update(entity);
		return R.ok();
	}


	//保存子列表信息
	public R saveItem(Map<String, Object> params,TcwExpenseSettleReturn entity) throws Exception{
		//保存列表信息
		List<Map<String, Object>> subDataList = new ArrayList<>();
		if(params.get("subData")!=null){
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData,44L);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		//删除列表信息
		financeMapper.deleteTcwExpenseSettleReturnItemByPbid(entity.getBid());
		for (int i = 0; i < subDataList.size(); i++) {
			Map<String, Object> item = subDataList.get(i);
			TcwExpenseSettleReturnItem itemInfo = JSON.parseObject(JSON.toJSONString(item), TcwExpenseSettleReturnItem.class);
			itemInfo.setStatus(1);
			itemInfo.setPbid(entity.getBid());
			if(item.get("vbz")!=null){
				itemInfo.setAccountDetailedRemark(item.get("vbz").toString());
			}
			//新增
			tcwExpenseSettleReturnItemMapper.insert(itemInfo);
			/*
			if(checkUtil.isNotNullByObject(itemInfo.getId())){
				//修改
				tcwExpenseSettleReturnItemMapper.update(itemInfo);
			}else {
				//新增
				tcwExpenseSettleReturnItemMapper.insert(itemInfo);
			}

			 */
		}
		return R.ok();
	}


	//删除
	@Override
	@Transactional
	public R del(Long id) throws Exception{
		if (id == null) {
			return R.error("ID不能为空");
		}
		TcwExpenseSettleReturn entity = new TcwExpenseSettleReturn().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		//删除
		tcwExpenseSettleReturnMapper.deleteTrue(id);
		//删除列表信息
		financeMapper.deleteTcwExpenseSettleReturnItemByPbid(entity.getBid());
		//删除流程
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}

	//删除子列表
	@Override
	@Transactional
	public R toDelByItem(Long id) throws Exception{
		tcwExpenseSettleReturnItemMapper.deleteTrue(id);
		return R.ok();
	}



	/**
	 * 流转通过
	 */
	@Override
	@Transactional
	public R flowPass(Long id, String loginUserId) throws Exception {

		TcwExpenseSettleReturn entity = new TcwExpenseSettleReturn().setId(id).queryFirst();
		Flow f = yspTaskService.flowPass(entity.getBid(), loginUserId);
		if (f.getCode() == Flow.Code.FAILED.value) {
			return R.error(f.getMsg());
		} else {
			if (f.getState() == Flow.State.FINISH.value) {
				flowFinish(entity.getBid());
			}
			return R.ok();
		}
	}

	/**
	 * 流转结束
	 */
	@Override
	@Transactional
	public void flowFinish(String bid) throws Exception {

		TcwExpenseSettleReturn entity = new TcwExpenseSettleReturn().setBid(bid).queryFirst();
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return;
		}
		Date theDate = new Date();
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		entity.setUpdateTime(theDate);

		//获取详情信息
		List<TcwExpenseSettleReturnItem> sonList = new TcwExpenseSettleReturnItem().setPbid(bid).queryList();
		for (TcwExpenseSettleReturnItem sonItem : sonList){
			//获取流水表信息
			TcwAccountDetailedForCompany tcwAccountDetailedForCompany = new TcwAccountDetailedForCompany()
					.setId(sonItem.getAccountDetailedForCompanyId()).queryFirst();
			if(tcwAccountDetailedForCompany!=null){
				/*
				 * 新增流水
				 * 必填：vgsbm划出公司编码；vgsbmp划入公司编码；vjylx交易类型；fje交易金额；djysj交易时间；dshsj审核时间；vbz备注
				 * 选填：mname;mtype;mnid;mbid;mguid；writeTime记账时间（如果为空，默认审核时间）
				 */
				BigDecimal returnAmount = sonItem.getReturnAmount();
				tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJcNoTrigger(
						tcwAccountDetailedForCompany.getVgsbm(),tcwAccountDetailedForCompany.getVgsjc(),
						tcwAccountDetailedForCompany.getVgsbmp(),tcwAccountDetailedForCompany.getVgsjcp(),
						tcwAccountDetailedForCompany.getVjylx(), returnAmount.negate(),tcwAccountDetailedForCompany.getCreateTime(), theDate,"费用结算返还单："+entity.getBid()+"，备注"+(tcwAccountDetailedForCompany.getVbz()!=null ? tcwAccountDetailedForCompany.getVbz():""),
						entity.getBid(),tcwAccountDetailedForCompany.getWriteTime());

				tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJcNoTrigger(
						tcwAccountDetailedForCompany.getVgsbmp(),tcwAccountDetailedForCompany.getVgsjcp(),
						tcwAccountDetailedForCompany.getVgsbm(),tcwAccountDetailedForCompany.getVgsjc(),
						tcwAccountDetailedForCompany.getVjylx(), returnAmount,tcwAccountDetailedForCompany.getCreateTime(), theDate,"费用结算返还单："+entity.getBid()+"，备注"+(tcwAccountDetailedForCompany.getVbz()!=null ? tcwAccountDetailedForCompany.getVbz():""),
						entity.getBid(),tcwAccountDetailedForCompany.getWriteTime());
			}

		}

		//修改信息
		tcwExpenseSettleReturnMapper.update(entity);

	}



	/**
	 * 参数验证
	 */
	public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCW_ExpenseSettleReturn",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
		return backMsg;
	}


	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		//获取pc字段数据
		List<YsGridCol> listField = new YsGridCol()
				.setGridId(gridId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		String backMsg = "";
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}
			//验证
			for(int i = 0;i<subDataList.size();i++){
				String backMsgByRow = "";
				Map<String, Object> subData = subDataList.get(i);
				//验证必填字段的非空；其他字段的长度限制、类型
				backMsgByRow += checkUtil.checkTableColLengthAndDataTypeByGrid(
						"TCW_ExpenseSettleReturnItem",
						listField,
						subData,
						ysColItem->
								ysColItem.getCode().equals("accountDetailedForCompanyId")
								|| ysColItem.getCode().equals("returnAmount")
				);
				//验证：返还金额≤交易金额
				if(checkUtil.isNotNullByObject(subData.get("returnAmount")) && checkUtil.isNotNullByObject(subData.get("fje"))){
					BigDecimal returnAmount = new BigDecimal(subData.get("returnAmount").toString());//返还金额
					BigDecimal fje = new BigDecimal(subData.get("fje").toString());//交易金额
					if(returnAmount.compareTo(fje)>0){
						backMsgByRow += "\"返还金额\" 不能大于 \"交易金额\"；";
					}
				}

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
				}
			}
		}else{
			backMsg = "列表信息为空";
		}
		checkByGrid.setErrMsg(backMsg);
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}


	//获取列表数据
	@Override
	@Transactional
	public Map<String,Object> getExtraParam( String bid) throws Exception{
		Map<String,Object> extraParam = new TcwExpenseSettleReturn()
				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid ")
				.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间
				.addLeftJoin("(SELECT ISNULL(SUM(S.ReturnAmount),0) AS returnAmount,S.Pbid FROM TCW_ExpenseSettleReturnItem S GROUP BY S.Pbid) B ON B.Pbid = A.Bid")
				.addField("B.returnAmount AS totalAmount")//付款总金额
				.setBid(bid)
				.queryFirstMap();
		return extraParam;
	}
	//获取子列表数据
	@Override
	@Transactional
	public List<Map<String, Object>> getItemList( String bid) throws Exception{
		List<Map<String, Object>> itemList = new TcwExpenseSettleReturnItem()
				.addLeftJoin("TCW_AccountDetailedForCompany D ON D.Id = A.AccountDetailedForCompanyId")//流水表
				//.addField("D.Guid AS guid")//流水唯一识别码
				.addField("D.Vjylx AS vjylx")//交易类型
				.addField("D.Vgsbm AS vgsbm")//运营公司编码
				.addField("D.Vgsjc AS vgsjc")//运营公司简称
				.addField("D.Vgsbmp AS vgsbmp")//对方公司编码
				.addField("D.Vgsjcp AS vgsjcp")//对方公司简称
				.addField("D.Fje AS fje")//交易金额
				.addField("D.Vbz AS vbz")//备注
				.addField("D.Djysj AS djysj")//交易发生时间
				.addField("D.Dshsj AS dshsj")//交易审核时间
				.addField("D.WriteTime AS writeTime")//记账时间

				.setPbid(bid)
				.queryMap();
		return itemList;
	}


}
